﻿new function(jQun, Class, Interface, Enum, HTMLElementList, HTML, Event, defineProperties){

this.FieldAreaActions = (function(){
	return new Enum(
		[ "Cancel", "OK" ]
	);
}());

this.FieldTypes = (function(){
	return new Enum(
		[ "Text", "Radio", "Checkbox" ]
	);
}());

this.ITemporaryFieldArea = (function(){
	return new Interface(
		[ "getValue" ],
		HTMLElementList.prototype
	);
}());

this.TemporaryFieldArea = (function(ITemporaryFieldArea, FieldAreaActions, html, cancelEvent, okEvent, document, remove, setTimeout){
	function TemporaryFieldArea(title, _text){
		///	<summary>
		///	临时的字段区域，如：文本输入、单选、多选等。
		///	</summary>
		///	<param name="title" type="String">提示用户的标题。</param>
		///	<param name="_text" type="String">ok按钮的文本。</param>
		var temporaryFieldArea = this;

		this.combine(
				html.create(
					{
						title : title,
						text : _text
					},
					true
				)
			)
			.attach({
				touchmove : function(e){
					e.preventDefault();
				},
				userclick : function(e, targetList){
					var buttonList = targetList.btw(">header>button", this);

					if(
						buttonList.length === 0
					){
						return;
					}

					buttonList.dispatch(
						buttonList.getData("action") - 0 === FieldAreaActions.OK ?
							okEvent :
							cancelEvent,
						{
							value : temporaryFieldArea.getValue()
						}
					);

					temporaryFieldArea.remove();
				}
			})
			.appendTo(
				document.body
			);
	};
	TemporaryFieldArea = new Class(TemporaryFieldArea, "jQun.TemporaryFieldArea", ITemporaryFieldArea);

	TemporaryFieldArea.override({
		remove : function(){
			///	<summary>
			///	重写remove方法，主要是为了css效果。
			///	</summary>
			var temporaryFieldArea = this;
		
			this.setData(
					"out"
				)
				// 防止再次点击出现其他效果
				.detach(
					{ userclick : arguments.callee }
				);
					
			setTimeout(
				function(){
					remove.call(temporaryFieldArea);
				},
				200
			);

			return this;
		}
	});

	TemporaryFieldArea.props({
		fillHTMLContent : function(htmlContent){
			///	<summary>
			///	向该临时区域填充html字符串，使其具有相关的内容。
			///	</summary>
			this.query(
					">blockquote"
				)
				.innerHTML = htmlContent;

			return this;
		},
		readOnly : function(){
			///	<summary>
			///	启用readOnly事件。
			///	</summary>

			// 默认禁止启用以下选择器元素
			this.query(
					[
						'header>button[data-action="' + FieldAreaActions.OK + '"]',
						"blockquote>button",
						"blockquote>input",
						"blockquote>textarea"
					].join(",")
				)
				.set(
					"disabled",
					true
				)
				.blur();

			return this;
		}
	});

	return TemporaryFieldArea.constructor;
}(
	this.ITemporaryFieldArea,
	this.FieldAreaActions,
	// html
	new HTML([
		'<div class="temporaryFieldArea">',
			'<header data-color="white">',
				'<button data-action="0">取消</button>',
				'<span>{title}</span>',
				'<button data-action="1">{text || "确定"}</button>',
			'</header>',
			'<blockquote data-color="black"></blockquote>',
		'</div>'
	].join("")),
	// cancelEvent
	new Event("cancel"),
	// okEvent
	new Event("ok"),
	document,
	HTMLElementList.prototype.remove,
	setTimeout
));

this.TemporaryTextarea = (function(TemporaryFieldArea, textareaHtml, passwordHtml){
	function TemporaryTextarea(title, _value, _text, _maxLength, _rows, _isPassword){
		///	<summary>
		///	为手机版文本输入区域定制一个临时输入区域，避免输入法的弹出造成视图差。
		///	</summary>
		///	<param name="title" type="String">提示用户的标题。</param>
		///	<param name="_value" type="String">现有的值。</param>
		///	<param name="_text" type="String">ok按钮的文本。</param>
		///	<param name="_maxLength" type="Number">文本长度最大值。</param>
		///	<param name="_rows" type="Number">输入区域的行数。</param>
		///	<param name="_isPassword" type="Boolean">是否为密码框。</param>
		var contentList;
		
		this.fillHTMLContent(
				(
					_isPassword ? passwordHtml : textareaHtml
				)
				.render({
					value : _value,
					maxLength : _maxLength,
					rows : _rows
				})
			)
			.classList
			.add(
				"temporaryTextarea"
			);

		contentList = this.query(">blockquote>*");

		contentList
			.attach({
				touchmove : function(e){
					// 停掉掉冒泡，因为父级可能会阻止浏览器默认事件（移动文本框选择光标）
					e.stopPropagation();
				}
			})
			.set(
				"selectionStart",
				contentList.value.length
			);

		if(
			!_maxLength
		){
			return;
		}

		this.attach({
			reposcursor : function(){
				contentList
					.parent()
					.setData(
						"surplus",
						_maxLength - contentList.value.length
					);
			}
		});
	};
	TemporaryTextarea = new Class(TemporaryTextarea, "jQun.TemporaryTextarea", TemporaryFieldArea.prototype);

	TemporaryTextarea.props({
		getValue : function(){
			///	<summary>
			///	获取值。
			///	</summary>
			return this.query(">blockquote>*").value;
		}
	});

	return TemporaryTextarea.constructor;
}(
	this.TemporaryFieldArea,
	// textareaHtml
	new HTML([
		'<textarea rows="{rows || 1}" autofocus maxlength="{maxLength || -1}">',
			'{?~value}',
		'</textarea>'
	].join("")),
	// passwordHtml
	new HTML([
		'<input type="password" autofocus maxlength="{maxLength || -1}" value="{?~value}" />'
	].join(""))
));

this.TemporaryCheckbox = (function(TemporaryFieldArea, html){
	function TemporaryCheckbox(title, options, _text){
		///	<summary>
		///	临时的多选框。
		///	</summary>
		///	<param name="title" type="String">提示用户的标题。</param>
		///	<param name="options" type="Array">现有的选项及值。</param>
		///	<param name="_text" type="String">ok按钮的文本。</param>
		var temporaryCheckbox = this;

		this.fillHTMLContent(
				html.render({
					options : options
				})
			)
			.attach({
				userclick : function(e, targetList){
					var buttonList = targetList.btw(">blockquote>button", this);

					if(
						buttonList.length === 0
					){
						return;
					}
					
					temporaryCheckbox[
						buttonList.getData("check") === null ? "check" : "uncheck"
					](
						buttonList.getData("key")
					);
				}
			})
			.classList
			.add(
				"temporaryCheckbox"
			);
	};
	TemporaryCheckbox = new Class(TemporaryCheckbox, "jQun.TemporaryCheckbox", TemporaryFieldArea.prototype);

	TemporaryCheckbox.props({
		check : function(key){
			///	<summary>
			///	选中指定关键字的checkbox。
			///	</summary>
			///	<param name="key" type="String">指定的关键字。</param>
			this.query(
					'>blockquote>button[data-key="' + key + '"]'
				)
				.setData(
					"check"
				);

			return this;
		},
		getValue : function(){
			///	<summary>
			///	获取值。
			///	</summary>
			var value = [];
			
			this.query(
					">blockquote>button[data-check]"
				)
				.forEach(function(button){
					var buttonList = new HTMLElementList(button);

					value.push({
						key : buttonList.getData("key"),
						text : buttonList.innerHTML
					});
				});

			return value;
		},
		uncheck : function(key){
			///	<summary>
			///	取消选中指定关键字的checkbox。
			///	</summary>
			///	<param name="key" type="String">指定的关键字。</param>
			this.query(
					'>blockquote>button[data-key="' + key + '"]'
				)
				.removeData(
					"check"
				);

			return this;
		}
	});

	return TemporaryCheckbox.constructor;
}(
	this.TemporaryFieldArea,
	// html
	new HTML([
		'@for(',
			'options ->> option',
		'){',
			'<button data-key="{option.key}" {option.checked ? "data-check" : ""}>{option.text}</button>',
		'}'
	].join(""))
));

this.TemporaryRadio = (function(TemporaryCheckbox, check, uncheck, getValue){
	function TemporaryRadio(title, options, _text){
		this.classList.add("temporaryRadio");
	};
	TemporaryRadio = new Class(TemporaryRadio, "jQun.TemporaryRadio", TemporaryCheckbox.prototype);

	TemporaryRadio.override({
		check : function(key){
			///	<summary>
			///	选中指定关键字的radio。
			///	</summary>
			///	<param name="key" type="String">指定的关键字。</param>
			var k = this.query(">blockquote>button[data-check]").getData("key");

			if(
				k !== key.toString()
			){
				uncheck.call(this, k);
				check.call(this, key);
			}

			return this;
		},
		getValue : function(){
			///	<summary>
			///	获取值。
			///	</summary>
			return getValue.call(this)[0];
		},
		uncheck : function(){
			///	<summary>
			///	重写此方法，因为不需要主动取消。
			///	</summary>
			return this;
		}
	});

	return TemporaryRadio.constructor;
}(
	this.TemporaryCheckbox,
	this.TemporaryCheckbox.prototype.check,
	this.TemporaryCheckbox.prototype.uncheck,
	this.TemporaryCheckbox.prototype.getValue
));

this.Fieldset = (function(
	TemporaryTextarea, TemporaryCheckbox, TemporaryRadio,
	Ajax,
	FieldTypes,
	FOCUS_ELEMENT_SELECTOR,
	clicksubmitEvent, focusEvent, getOptions
){
	function Fieldset(selector){
		///	<summary>
		///	数据区域。
		///	</summary>
		///	<param name="selector" type="String">元素选择器。</param>
		this.classList.add("fieldset");

		this.attach({
			userclick : function(e, targetList){
				var buttonList = targetList.btw("button[data-submit]", this);

				// 如果点击的不是提交按钮
				if(
					buttonList.length === 0
				){
					return;
				}

				buttonList.dispatch(clicksubmitEvent);
			}
		});

		this.initFieldAreas();
	};
	Fieldset = new Class(Fieldset, "jQun.Fieldset", HTMLElementList.prototype);

	Fieldset.props({
		disableAll : function(_except){
			this.query(
					FOCUS_ELEMENT_SELECTOR
				)
				.set(
					"readOnly",
					true
				);

			this.query(
					"button"
				)
				.set(
					"disabled",
					true
				);

			return this;
		},
		enableAll : function(){
			this.query(
					FOCUS_ELEMENT_SELECTOR
				)
				.set(
					"readOnly",
					false
				);

			this.query(
					"button"
				)
				.set(
					"disabled",
					false
				);

			return this;
		},
		initFieldAreas : function(){
			var fieldset = this, timeStamp = 0, target = null;

			// 监听聚焦事件
			this.query(
				FOCUS_ELEMENT_SELECTOR
			)
			.attach({
				touchstart : function(e){
					timeStamp = e.timeStamp;
					target = e.target;
				},
				touchend : function(e, targetList){
					if(
						e.target !== target
					){
						return;
					}

					if(
						e.timeStamp - timeStamp > 200
					){
						return;
					}

					e.preventDefault();
					targetList.dispatch(focusEvent);
				},
				focus : function(e, targetList){
					this.blur();

					var temporaryFieldArea, fieldtype = targetList.getData("fieldtype") - 0;

					if(
						fieldtype === FieldTypes.Text
					){
						temporaryFieldArea = fieldset.showTemporaryTextarea(
							this,
							targetList.getData("title") || targetList.get("placeholder"),
							targetList.get("maxLength"),
							targetList.getData("rows"),
							this.type.toLowerCase() === "password"
						);
					}
					else {
						temporaryFieldArea = fieldset[
							fieldtype === FieldTypes.Radio ? "showTemporaryRadio" : "showTemporaryCheckbox"
						](
							this,
							targetList.getData("title") || targetList.get("placeholder"),
							targetList.getData("listname"),
							targetList.getData("key")
						);
					}

					if(
						!this.readOnly
					){
						return;						
					}

					temporaryFieldArea.readOnly();
				}
			});

			// 单选、多选根据key来显示初始值
			this.query(
					[
						'[data-fieldtype="' + FieldTypes.Radio +  '"]',
						'[data-fieldtype="' + FieldTypes.Checkbox +  '"]'
					].join(",")
				)
				.forEach(
					function(element){
						var values = [], list = new HTMLElementList(element);

						getOptions(
								this,
								list.getData("listname"),
								list.getData("key")
							)
							.forEach(function(option){
								if(
									!option.checked
								){
									return;
								}

								values.push(option.text);
							});

						element.value = values.join(" ");
					},
					this
				);

			return this;
		},
		reset : function(){
			///	<summary>
			///	重置数据。
			///	</summary>

			// 清除错误信息
			this.query(
					'[data-error]'
				)
				.removeData(
					"error"
				);

			// 清空文本框
			this.query(
					"input:not([data-fieldtype]), textarea"
				)
				.value = "";

			return this;
		},
		showError : function(input){
			///	<summary>
			///	显示错误信息提示。
			///	</summary>
			///	<param name="input" type="HTMLInputElement">出错的输入框。</param>
			var inputList = new HTMLElementList(input);
				
			inputList[0].scrollIntoView();

			alert(
				inputList.getData("errortext")
			);

			return this;
		},
		showTemporaryCheckbox : function(target, title, listname, key){
			return new TemporaryCheckbox(
					title,
					getOptions(this, listname, key)
				)
				.attach({
					ok : function(e){
						var value = e.value, texts = [], keys = [];

						value.forEach(function(val){
							texts.push(val.text);
							keys.push(val.key);
						});

						target.value = texts.join(" ");
						target.setAttribute("data-key", keys.join(","));
					}
				});
		},
		showTemporaryRadio : function(target, title, listname, key){
			return new TemporaryRadio(
					title,
					getOptions(this, listname, key)
				)
				.attach({
					ok : function(e){
						var value = e.value;

						target.value = value.text;
						target.setAttribute("data-key", value.key);
					}
				});
		},
		showTemporaryTextarea : function(target, title, _maxLength, _rows, _isPassword){
			///	<summary>
			///	显示临时输入区域。
			///	</summary>
			///	<param name="input" type="HTMLInputElement">用于回调数据的输入框。</param>
			return new TemporaryTextarea(
					title,
					target.value,
					null,
					_maxLength,
					_rows,
					_isPassword
				)
				.attach({
					ok : function(e){
						target.value = e.value;
					}
				});
		},
		submit : function(name, params, callback, _error, _beforeSend, _progress){
			///	<summary>
			///	提交数据。
			///	</summary>
			///	<param name="name" type="String">ajax名称。</param>
			///	<param name="params" type="Object">ajax数据。</param>
			///	<param name="callback" type="Function">回调函数。</param>
			///	<param name="_error" type="Function">错误回调函数。</param>
			///	<param name="_beforeSend" type="Function">在发送请求之前的回调函数。</param>
			///	<param name="_progress" type="Function">数据上传进度回调函数。</param>
			var submitButtonList = this.query("button[data-submit]");

			// 提交按钮设置不可用
			submitButtonList.set("disabled", true);

			Ajax.open(
				name,
				params,
				function(data){
					// 恢复提交按钮
					submitButtonList.set("disabled", false);

					callback(data);
				},
				function(){
					// 恢复提交按钮
					submitButtonList.set("disabled", false);
					
					if(
						typeof _error === "function"
					){
						_error();
					}
				},
				_beforeSend,
				_progress
			);

			return this;
		}
	});

	return Fieldset.constructor;
}(
	this.TemporaryTextarea,
	this.TemporaryCheckbox,
	this.TemporaryRadio,
	jQun.Ajax,
	this.FieldTypes,
	// FOCUS_ELEMENT_SELECTOR
	'input[type="text"], input[type="password"], textarea',
	// clicksubmitEvent
	new Event("clicksubmit"),
	// focusEvent
	new Event("focus", "Event", [false]),
	// getOptions
	function(fieldset, listname, key){
		var options = [], keys = key.split(",") ;

		fieldset
			.query(
				'*[data-list="' + listname + '"] > *'
			)
			.forEach(function(element){
				var elementList = new HTMLElementList(element), key = elementList.getData("key");

				options.push({
					key : key,
					text : elementList.innerHTML,
					checked : keys.indexOf(key) > -1
				});
			});

		return options;
	}
));

defineProperties(jQun, this);
}(
	jQun,
	jQun.Class,
	jQun.Interface,
	jQun.Enum,
	jQun.HTMLElementList,
	jQun.HTML,
	jQun.Event,
	jQun.defineProperties
);